package oss

import (
	//	"fmt"
	//	"io"
	"net/http"
	//	"net/url"
	//	"sort"
	//	"strings"
	"errors"
	"net"
	"strings"
)

type OssAPI struct {
	host            string
	accessKeyID     string
	accessKeySecret string
	isSecurity      bool
	stsToken        string
	client          *http.Client
	debug           bool
	timeout         int
	retryTimes      int
	ossDomain       bool
	bucket          string

	currentRequestId  string
	currentObjectType string
}

var (
	ErrInvalidHost = errors.New("invalid host")
)

// getOssHost is hosts a valid host in
func findFirstAvailableOssHost(hosts string) (string, error) {
	hs := strings.Split(hosts, ",")
	if len(hs) <= 1 {
		return hosts, nil
	}

	for _, h := range hs {
		h = strings.TrimSpace(h)
		tcpAddr, err := net.ResolveTCPAddr("tcp", h)
		if err != nil {
			continue
		}

		conn, err := net.DialTCP("tcp", nil, tcpAddr)
		if err != nil {
			continue
		}

		defer conn.Close()
		return h, nil
	}
	return "", ErrInvalidHost
}

func NewOssAPI(hosts string, bucket string, accessKeyID string, accessKeySecret string, isSecurity bool, stsToken string, client *http.Client) *OssAPI {
	if client == nil {
		client = http.DefaultClient
	}

	host, err := findFirstAvailableOssHost(hosts)
	if err != nil {
		return nil
	}

	if !isValidBucketName(bucket) {
		return nil
	}

	return &OssAPI{
		host:            host,
		accessKeyID:     accessKeyID,
		accessKeySecret: accessKeySecret,
		isSecurity:      isSecurity,
		stsToken:        stsToken,
		client:          client,
		timeout:         60,
		debug:           false,
		retryTimes:      5,
		ossDomain:       false,
		bucket:          bucket,
	}
}

func (o OssAPI) setRetryTimes(retryTimes int) {
	o.retryTimes = retryTimes
}

func (o OssAPI) setDebug(debug bool) {
	o.debug = debug
}

func (o OssAPI) setTimeout(timeout int) {
	o.timeout = timeout
}

func (o OssAPI) setOssDomain(ossDomain bool) {
	o.ossDomain = ossDomain
}

type OssError struct {
	error
	code int
	msg  string
}

func NewOssError(code int, msg string) error {
	return &OssError{
		code: code,
		msg:  msg,
	}
}

//
//func (e OssError) String() string {
//	return fmt.Sprintf("error code :%d, error msg :%s", e.code, e.msg)
//}
